package com.bobi.tfca.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bobi.tfca.dao.MessageDao;
import com.bobi.tfca.model.entity.GroupMessageEntity;
import com.bobi.tfca.model.entity.MemberEntity;
import com.bobi.tfca.model.entity.MessageEntity;
import com.bobi.tfca.model.enums.MessageCategoryEnum;
import com.bobi.tfca.model.enums.MessageContentTypeEnum;
import com.bobi.tfca.model.enums.MessageStatusEnum;
import com.bobi.tfca.model.vo.MessageVO;
import com.bobi.tfca.service.GroupMessageService;
import com.bobi.tfca.service.MemberService;
import com.bobi.tfca.service.MessageService;
import com.bobi.tfca.utils.DateTimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 消息服务层实现
 *
 * @author 李文发
 * @date 2024/4/3
 */
@Service
@Slf4j
public class MessageServiceImpl extends ServiceImpl<MessageDao, MessageEntity> implements MessageService {

    @Autowired
    private GroupMessageService groupMessageService;

    @Autowired
    private MemberService memberService;

    @Autowired
    private MessageDao messageDao;


    /**
     * 查询聊天室历史信息
     *
     * @param groupId 聊天室id
     * @param member
     * @return 消息列表
     */
    @Override
    public List<MessageVO> getCRHistoryMessages(Integer groupId, MemberEntity member) {
        // 更新该用户在该群的所有未读消息为已读
        messageDao.updateMemberURMsg2Read(groupId, member.getMemberId());

        List<MessageEntity> messageEntityList = new ArrayList<>();
        // 查询消息
        LambdaQueryWrapper<GroupMessageEntity> querywrapper1 = new LambdaQueryWrapper<>();
        List<GroupMessageEntity> groupMessageEntities = groupMessageService.list(querywrapper1.eq(GroupMessageEntity::getGroupId, groupId));
        if (groupMessageEntities == null || groupMessageEntities.size() == 0) {
            return new ArrayList<>();
        }

        for (GroupMessageEntity groupMessageEntity : groupMessageEntities) {
            LambdaQueryWrapper<MessageEntity> queryWrapper2 = new LambdaQueryWrapper<>();
            queryWrapper2.eq(MessageEntity::getCategory, MessageCategoryEnum.GROUP_CHAT.getCode());
            queryWrapper2.eq(MessageEntity::getMessageId, groupMessageEntity.getMessageId());
            MessageEntity message = this.getOne(queryWrapper2);
            messageEntityList.add(message);
        }
        // 按时间排序
        messageEntityList.sort(Comparator.comparing(MessageEntity::getSendTime));
        // 按一分钟为顺序，从后往前每一个相差一分钟，则设置显示发送时间
        // 如果列表中的元素少于两个，则直接设置当前消息时间可见
        long oneMinuteInMillis = 60 * 1000; // 一分钟的毫秒数，如果连续的间隔内发送的
        // 从倒数第二个元素开始向前遍历
        for (int i = messageEntityList.size() - 2; i >= 0; i--) {
            MessageEntity currentMessage = messageEntityList.get(i);
            MessageEntity previousMessage = messageEntityList.get(i + 1);

            // 计算当前消息与前一个消息的时间差
            long timeDifference = Math.abs(currentMessage.getSendTime().getTime() - previousMessage.getSendTime().getTime());

            // 如果时间差小于一分钟，则将当前消息的显示属性设置为 false
            // 如果时间差大于或一分钟，则将当前消息的显示属性设置为 true
            currentMessage.setIsTimeVisible(timeDifference >= oneMinuteInMillis);
        }
        if (messageEntityList.size() != 0) {
            if (messageEntityList.size() == 1) {
                MessageEntity message = messageEntityList.get(0);
                if (message != null) {
                    message.setIsTimeVisible(true);
                }
            } else {
                // 给最新的设置时间
                MessageEntity message1 = messageEntityList.get(messageEntityList.size() - 1);
                MessageEntity message2 = messageEntityList.get(messageEntityList.size() - 2);
                long timeDifference = message1.getSendTime().getTime() - message2.getSendTime().getTime();

                // 最开始和最末尾的消息一定要设置时间，最末尾的在开始设置了
                message1.setIsTimeVisible(timeDifference > oneMinuteInMillis);
                MessageEntity oldestMessage = messageEntityList.get(0);
                oldestMessage.setIsTimeVisible(true);
            }
        }

        return messageEntityList.stream().map(it -> {
            MessageVO vo = new MessageVO();
            BeanUtil.copyProperties(it, vo, "sendTime");
            if (it.getIsTimeVisible()) {
                Timestamp timestamp = it.getSendTime();
                // 如果是今天，格式不一样
                if (DateTimeUtil.isToday(timestamp)) {
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");
                    String format = timestamp.toLocalDateTime().format(formatter);
                    vo.setSendTime(format);
                } else if (DateTimeUtil.isThisYear(timestamp)) {
                    // 如果是今年
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd HH:mm");
                    String format = timestamp.toLocalDateTime().format(formatter);
                    vo.setSendTime(format);
                } else {
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                    String format = timestamp.toLocalDateTime().format(formatter);
                    vo.setSendTime(format);
                }
            }
            // 设置发送人照片和姓名
            MemberEntity sender = memberService.getById(it.getSenderId());
            vo.setSenderName(sender.getMemberName());
            vo.setSenderPicture(sender.getPicture());
            return vo;
        }).toList();
    }

    @Override
    public List<MessageVO> findAllLetters(Integer memberId) {
        List<MessageVO> messageVOList = new ArrayList<>();

        // 查询所有发送者或接收者是当前用户的信件
        LambdaQueryWrapper<MessageEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MessageEntity::getCategory, MessageCategoryEnum.LETTER.getCode());
        queryWrapper.and(wrapper -> {
            wrapper.eq(MessageEntity::getSenderId, memberId)
                    .or()
                    .eq(MessageEntity::getReceiverId, memberId);
        });
        queryWrapper.orderByDesc(MessageEntity::getSendTime);
        List<MessageEntity> list = this.list(queryWrapper);

        list.forEach(it -> {
            // 将内容设置为空，避免查消息内容太大
            it.setContent(null);
            MessageVO messageVO = fillDetail(it);
            messageVOList.add(messageVO);
        });
        // 填补收件人姓名和发送人姓名
        return messageVOList;
    }

    /**
     * 填补收件人姓名和发送人姓名
     */
    private MessageVO fillDetail(MessageEntity entity) {
        // 查询发送人姓名
        MemberEntity sender = memberService.getById(entity.getSenderId());
        // 查询接收人姓名
        MemberEntity receiver = memberService.getById(entity.getReceiverId());
        MessageVO messageVO = MessageVO.ofMessageEntity(entity);
        messageVO.setSenderName(sender.getMemberName());
        messageVO.setReceiverName(receiver.getMemberName());
        messageVO.setSenderPicture(sender.getPicture());
        return messageVO;
    }

    @Override
    public List<MessageVO> findAllNotifications(Integer memberId) {
        List<MessageVO> messageVOList = new ArrayList<>();
        // 查询接收的通知，自己发的同样也会发一份给自己
        LambdaQueryWrapper<MessageEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MessageEntity::getReceiverId, memberId)
                .eq(MessageEntity::getCategory, MessageCategoryEnum.NOTIFICATION.getCode())
                .orderByDesc(MessageEntity::getSendTime);
        List<MessageEntity> list = this.list(queryWrapper);
        // 填补收件人姓名和发送人姓名
        list.forEach(it -> {
            MessageVO messageVO = fillDetail(it);
            messageVOList.add(messageVO);
        });
        return messageVOList;
    }

    @Override
    public MessageVO getLetterById(MemberEntity member, Long letterId) {
        LambdaQueryWrapper<MessageEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MessageEntity::getCategory, MessageCategoryEnum.LETTER.getCode())
                .eq(MessageEntity::getMessageId, letterId);
        MessageEntity entity = this.getOne(queryWrapper);

        // 更新消息状态，为了设置消息状态为已读。这里不管是已读未读都更新
        if (Objects.equals(entity.getReceiverId(), member.getMemberId())) {
            entity.setMessageStatus(MessageStatusEnum.READ.getCode());
            this.updateById(entity);
        }
        return fillDetail(entity);
    }

    @Override
    public MessageVO getNotificationById(MemberEntity member, Long notificationId) {
        LambdaQueryWrapper<MessageEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MessageEntity::getCategory, MessageCategoryEnum.NOTIFICATION.getCode())
                .eq(MessageEntity::getMessageId, notificationId);
        MessageEntity entity = this.getOne(queryWrapper);

        // 更新消息状态，为了设置消息状态为已读。这里不管是已读未读都更新
        if (Objects.equals(entity.getReceiverId(), member.getMemberId())) {
            entity.setMessageStatus(MessageStatusEnum.READ.getCode());
            this.updateById(entity);
        }
        return fillDetail(entity);
    }

    @Override
    public Boolean writeLetter(Integer memberId, Integer receiverId, String letterContent) {
        MemberEntity receiver = memberService.getById(receiverId);
        if (receiver == null) {
            return false;
        }
        MessageEntity messageEntity = new MessageEntity();
        messageEntity.setContent(letterContent);
        messageEntity.setSenderId(memberId);
        messageEntity.setReceiverId(receiverId);
        messageEntity.setSendTime(Timestamp.valueOf(LocalDateTime.now()));
        messageEntity.setCategory(MessageCategoryEnum.LETTER.getCode());
        messageEntity.setContentType(MessageContentTypeEnum.TEXT.getCode());
        messageEntity.setMessageStatus(MessageStatusEnum.RECEIVED.getCode());
        this.save(messageEntity);
        return true;
    }

    @Override
    public Boolean publishNotification(Integer memberId, String notificationContent) {
        // TODO 目前通知发送给了全体成员
        LambdaQueryWrapper<MemberEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(MemberEntity::getMemberId);
        List<MemberEntity> list = memberService.list(queryWrapper);
        List<MessageEntity> messages = new ArrayList<>();
        list.forEach(it -> {
            MessageEntity messageEntity = new MessageEntity();
            messageEntity.setContent(notificationContent);
            messageEntity.setSenderId(memberId);
            messageEntity.setReceiverId(it.getMemberId());
            if (Objects.equals(it.getMemberId(), memberId)) {
                messageEntity.setMessageStatus(MessageStatusEnum.READ.getCode());
            } else {
                messageEntity.setMessageStatus(MessageStatusEnum.RECEIVED.getCode());
            }
            messageEntity.setSendTime(Timestamp.valueOf(LocalDateTime.now()));
            messageEntity.setCategory(MessageCategoryEnum.NOTIFICATION.getCode());
            messageEntity.setContentType(MessageContentTypeEnum.TEXT.getCode());
            messages.add(messageEntity);
        });
        this.saveBatch(messages);

        return true;
    }

    @Override
    public Integer getUnReadNotificationNum(Integer memberId) {
        LambdaQueryWrapper<MessageEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MessageEntity::getReceiverId, memberId)
                .eq(MessageEntity::getCategory, MessageCategoryEnum.NOTIFICATION.getCode())
                .eq(MessageEntity::getContentType, MessageContentTypeEnum.TEXT.getCode())
                .eq(MessageEntity::getMessageStatus, MessageStatusEnum.RECEIVED.getCode());
        long count = this.count(queryWrapper);
        return (int)count;
    }

    @Override
    public Integer getUnReadLetterNum(Integer memberId) {
        LambdaQueryWrapper<MessageEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MessageEntity::getReceiverId, memberId)
                .eq(MessageEntity::getCategory, MessageCategoryEnum.LETTER.getCode())
                .eq(MessageEntity::getContentType, MessageContentTypeEnum.TEXT.getCode())
                .eq(MessageEntity::getMessageStatus, MessageStatusEnum.RECEIVED.getCode());
        long count = this.count(queryWrapper);
        return (int)count;
    }

    @Override
    public long getUnReadMessageNum(Integer memberId, Integer groupId) {
        return groupMessageService.getUnReadMessageNum(memberId, groupId);
    }

    /**
     * 更新群消息为已读
     * @param messageId
     * @param member
     */
    @Override
    public void updateGroupMessageRead(Long messageId, MemberEntity member) {
        log.info("更新消息状态，----{}, ------{}", messageId, member.getMemberId());
        messageDao.updateGroupMessageRead(messageId, member.getMemberId());
    }

    @Override
    public Boolean checkNewMessage(MemberEntity member) {
        Integer unReadLetterNum = getUnReadLetterNum(member.getMemberId());
        if (unReadLetterNum > 0) {
            return true;
        }
        Integer unReadNotificationNum = getUnReadNotificationNum(member.getMemberId());
        if (unReadNotificationNum > 0) {
            return true;
        }
        return groupMessageService.checkNewGroupMsg(member.getMemberId());
    }
}
